package client

import (
	"sync"
	"time"
	"ws-demo-go/pkg/logger"
	"ws-demo-go/pkg/ws/client"
	"ws-demo-go/pkg/ws/common"
)

const (
	monitorInterval      = 5 * time.Second  // 监视连接是否断开的周期
	retryConnectInterval = 10 * time.Second // 重试连接的周期
)

type Client struct {
	serverAddr string            // 服务端地址（如 "ws://localhost:8080/ws"）
	conn       *connection       // 客户端连接实例
	reconnect  bool              // 是否自动重连
	mu         sync.Mutex        // 保护 conn 状态
	onMessage  func(data []byte) // 消息接收回调（交给上层处理）
}

// NewClient 创建客户端实例
func NewClient(serverAddr string, reconnect bool) *Client {
	return &Client{
		serverAddr: serverAddr,
		reconnect:  reconnect,
	}
}

// Connect 连接服务端
func (tc *Client) Connect() error {
	tc.mu.Lock()
	defer tc.mu.Unlock()

	// 拨号连接服务端
	wsConn, _, err := client.DefaultDialer.Dial(tc.serverAddr, nil)
	if err != nil {
		return err
	}

	// 创建客户端连接实例
	tc.conn = newConnection(&wsConn)
	logger.Info("Connected to server: %s", tc.serverAddr)

	// 设置 onMessage 回调
	tc.conn.onMessage = tc.onMessage

	// 启动多个循环
	go tc.conn.readLoop()
	go tc.conn.writeLoop()
	go tc.conn.sendPingLoop()
	go tc.conn.checkPongLoop()

	// 启动重连监控（如果需要）
	if tc.reconnect {
		go tc.monitorReconnect()
	}
	return nil
}

// SendBytes 发送字节流数据
func (tc *Client) SendBytes(data []byte) error {
	tc.mu.Lock()
	defer tc.mu.Unlock()
	if tc.conn == nil || tc.conn.isClosed() {
		return common.ErrNotConnected
	}
	return tc.conn.sendBytes(data)
}

// IsClosed 检查连接是否关闭
func (tc *Client) IsClosed() bool {
	return tc.conn == nil || tc.conn.isClosed()
}

// Close 关闭连接
func (tc *Client) Close() {
	tc.conn.close()
}

// SetOnMessage 设置消息处理器
func (tc *Client) SetOnMessage(messageHandler func(data []byte)) {
	tc.onMessage = messageHandler
}

// 监控连接状态，断开时自动重连
func (tc *Client) monitorReconnect() {
	for {
		if tc.conn.isClosed() {
			logger.Info("connection lost, reconnecting...")
			// 重试连接
			for {
				if err := tc.Connect(); err == nil {
					break
				}
				time.Sleep(retryConnectInterval)
			}
		}
		time.Sleep(monitorInterval)
	}
}
